package com.tc.data.datasource;

import com.tc.data.common.holder.StrategyHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.annotation.PostConstruct;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.sql.DataSource;
import java.lang.management.ManagementFactory;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 分库数据源
 * 
 * @author Anders
 * 
 */
public class RepositoryShardingDataSource extends AbstractRoutingDataSource
		implements RepositoryShardingDataSourceMBean {

	private static final Logger LOGGER = LoggerFactory.getLogger(RepositoryShardingDataSource.class);

	private Set<String> markDownSet = new CopyOnWriteArraySet<String>();
	private Map<String, DataSource> dataSources;
	private Map<String, String> atomToGroupMap;
	private String matrixName;
	private Map<Object, Object> prehotWriteDataSource;

	@Override
	protected Object determineCurrentLookupKey() {
		String key = StrategyHolder.getRepositoryShardingKey();
		LOGGER.debug(">>>>>>>>>> determin current repository sharding key is {}", key);

		// if (key != null && markDownSet.contains(key)) {
		// if (logger.isDebugEnabled()) {
		// logger.debug("get into mark down[" + key + "]");
		// }
		//
		// StrategyHolder.removeRepositoryShardingStrategy();
		// if (logger.isDebugEnabled()) {
		// logger.debug("clean up sharding holder before throw access denied
		// exception[" + key + "]");
		// }
		// throw new RuntimeException("access denied for " + key);
		// }

		return key;

	}

	@PostConstruct
	public void register() {
		synchronized (this) {
			MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
			ObjectName objectName;
			try {
				objectName = new ObjectName("com.vip.venus.data:type=" + this.toString());
				if (!mbeanServer.isRegistered(objectName)) {
					mbeanServer.registerMBean(this, objectName);
					if (LOGGER.isDebugEnabled()) {
						LOGGER.debug("com.vip.venus.data:type=" + this.toString() + " registered successfully");
					}
				}
			} catch (Exception e) {
				LOGGER.error(e.getMessage());
			}
		}
	}

	@Override
	public void putKey(String key) {
		this.markDownSet.add(key);
	}

	@Override
	public void removeKey(String key) {
		this.markDownSet.remove(key);
	}

	@Override
	public Set<String> getMarkDownKeys() {
		return markDownSet;
	}

	public Map<String, DataSource> getDataSources() {
		return dataSources;
	}

	public void setDataSources(Map<String, DataSource> dataSources) {
		this.dataSources = dataSources;
	}

	public String getMatrixName() {
		return matrixName;
	}

	public void setMatrixName(String matrixName) {
		this.matrixName = matrixName;
	}

	public Map<String, String> getAtomToGroupMap() {
		return atomToGroupMap;
	}

	public void setAtomToGroupMap(Map<String, String> atomToGroupMap) {
		this.atomToGroupMap = atomToGroupMap;
	}
	
	

	@Override
	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
		this.prehotWriteDataSource = targetDataSources;
		super.setTargetDataSources(targetDataSources);
	}

	public Map<Object, Object> getPrehotWriteDataSource() {
		return prehotWriteDataSource;
	}

	
	public DataSource resolveSpecifiedDataSource(Object dataSource)
			throws IllegalArgumentException {
		return super.resolveSpecifiedDataSource(dataSource);
	}

	@Override
	public void afterPropertiesSet() {
		super.afterPropertiesSet();
		//MetricRegister.registerMetric(this, matrixName, atomToGroupMap, dataSources);
	}

}
